package com.personnalManagerSystem.shiro;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.personnalManagerSystem.model.*;
import com.personnalManagerSystem.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author liqing
 * @Date: 2022/3/27 19:20
 * @Description
 */
@Slf4j
public class MyRealm  extends AuthorizingRealm {
    @Autowired
    IUserService iUserService;
    @Autowired
    IRoleService iRoleService;
    @Autowired
    IPermissionService iPermissionService;
    @Autowired
    IUserRoleService iUserRoleService;
    @Autowired
    IRolePermissionService iRolePermissionService;
    //授权由开发者提供shiro框架已经认证过的用户权限的信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //从session中获取当前用户的信息
        User user = (User)SecurityUtils.getSubject().getSession().getAttribute("user");
        //得到userId
        Integer userId = user.getUserId();
        //在user_role关系表中根据user_id来查询相应的角色
        List<UserRole> userRoles = iUserRoleService.list(new QueryWrapper<UserRole>().eq("user_id", userId));
        //从角色表中获取到角色id表()List.stream()取List对象指定字段组成map
        List<Integer> roleIds = userRoles.stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());
        //获取在角色id表中的角色记录
        List<Role> roleList = iRoleService.list();
        //使用Lamda来进行过滤
        roleList.removeIf(Role -> !roleIds.contains(Role.getRoleId()));
        //把筛选完成的角色编号放在set集合中
        Set<String> roles = roleList.stream()
                .map(Role::getRoleCode)  //角色的编码
                .collect(Collectors.toSet());
        log.info("{}",roles);
        //获取对应角色id对应的权限id
        List<Integer> permissionIds = iRolePermissionService.list()
                .stream()
                .filter(RolePermission -> roleIds.contains(RolePermission.getRoleId()))
                .map(RolePermission::getPermissionId)
                .collect(Collectors.toList());
        //获取对应的权限
        Set<String> permissionSet = iPermissionService.list()
                .stream()
                .filter(Permission -> permissionIds.contains(Permission.getPermissionId()))
                .map(Permission::getPermissionCode)  //权限的编码
                .collect(Collectors.toSet());
        log.info("{}",permissionSet);
        //创建授权对象,并将权限set和角色set存入授权信息
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1.获取用户名
        String principal = (String)token.getPrincipal();
        //2.从数据库中获取用户
        User user = iUserService.getOne(new QueryWrapper<User>().eq("username", principal));
        //3.如果没有用户则抛出空指针异常
        if(user==null){
            throw  new UnknownAccountException();
        }
        log.info("{}",user);
        //4.如果不为空则将该用户存入session中
        SecurityUtils.getSubject().getSession().setAttribute("user",user);
        //获取盐值(将其转换为二进制)
        ByteSource salt = ByteSource.Util.bytes(user.getSalt());
        //5.创建认证信息对象并返回认证信息
        return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),salt,this.getName());
    }
}
